﻿using ICSharpCode.SharpZipLib.Zip;
using Learun.Application.Base.SystemModule;
using Learun.Application.TwoDevelopment.ZZDT_EC;
using Learun.Application.Web.Common;
using Learun.Util;
using Learun.Util.Operat;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using SystemIO = System.IO;

namespace Learun.Application.Web.Areas.ZZDT_EC.Controllers
{
    /// <summary>
    /// 版 本 PIT-ADMS V7.0.3 敏捷开发框架
    /// Copyright (c) 2013-2018 Hexagon PPM
    /// 创 建：超级管理员
    /// 日 期：2022-04-11 09:45
    /// 描 述：项目备份表
    /// </summary>
    public class ec_project_bakupController : MvcControllerBase
    {
        private ec_project_bakupIBLL ec_project_bakupIBLL = new ec_project_bakupBLL();

        #region 视图功能

        /// <summary>
        /// 主页面
        /// <summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }
        /// <summary>
        /// 表单页
        /// <summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult Form()
        {
            return View();
        }
        #endregion

        #region 获取数据

        /// <summary>
        /// 获取页面显示列表数据
        /// <summary>
        /// <param name="queryJson">查询参数</param>
        /// <returns></returns>
        [HttpGet]
        [AjaxOnly]
        public ActionResult GetPageList(string pagination, string queryJson)
        {
            Pagination paginationobj = pagination.ToObject<Pagination>();
            var data = ec_project_bakupIBLL.GetList(queryJson, paginationobj);
            var jsonData = new
            {
                rows = data,
                total = paginationobj.total,
                page = paginationobj.page,
                records = paginationobj.records
            };
            return Success(jsonData);
        }
        /// <summary>
        /// 获取表单数据
        /// <summary>
        /// <returns></returns>
        [HttpGet]
        [AjaxOnly]
        public ActionResult GetFormData(string keyValue)
        {
            var ec_project_bakupData = ec_project_bakupIBLL.GetEntity(keyValue);
            var jsonData = new
            {
                ec_project_bakup = ec_project_bakupData,
            };
            return Success(jsonData);
        }
        #endregion

        #region 提交数据

        /// <summary>
        /// 删除实体数据
        /// <param name="keyValue">主键</param>
        /// <summary>
        /// <returns></returns>
        [HttpPost]
        [AjaxOnly]
        public ActionResult DeleteForm(string keyValue)
        {
            ec_project_bakupIBLL.DeleteEntity(keyValue);
            return Success("删除成功！", "项目备份", OperationType.Delete, null, null);
        }

        /// <summary>
        /// 保存实体数据（新增、修改）
        /// <param name="keyValue">主键</param>
        /// <summary>
        /// <returns></returns>
        [HttpPost]
        [ValidateAntiForgeryToken]
        [AjaxOnly]
        public ActionResult SaveForm(string keyValue, string strEntity)
        {
            ec_project_bakupEntity entity = strEntity.ToObject<ec_project_bakupEntity>();
            ec_project_bakupIBLL.OnlySaveEntity(keyValue, entity);
            return Success("保存成功！", "项目备份", string.IsNullOrEmpty(keyValue) ? OperationType.Create : OperationType.Update, null, null);
        }
        #endregion

        #region 项目备份还原功能
        /// <summary>
        /// 项目备份
        /// </summary>
        /// <returns></returns>
        public ActionResult ProjectBackup(string ProjectId, string ProjectIndex, string ProjectName)
        {
            UserInfo userInfo = LoginUserInfo.Get();
            //获取要备份的数据库表名
            List<string> list_tblName = BackupTable.GetBackupTableList();
            list_tblName.Add("lr_base_annexesfile");
            string filename = ProjectName + "_备份_" + DateTime.Now.ToString("yyyyMMddHHmmss");//文件名
            string filePath = string.Format("{0}/{1}/{2}/{3}/{4}/{5}", Config.GetValue("AnnexesFile"), "Backup", LoginUserInfo.Get().userId, DateTime.Now.ToString("yyyyMMdd"), Guid.NewGuid().ToString("D"), filename);
            string ZipFilesPath = filePath + ".zip";//ZIP包存放的路径
            long fileSize = 0;
            new TaskFactory().StartNew(() =>
            {
                try
                {
                    string sqlitePath = Path.Combine(filePath, "dbbackup");
                    if (!Directory.Exists(sqlitePath))
                    {
                        Directory.CreateDirectory(sqlitePath);
                    }

                    sqlitePath = Path.Combine(sqlitePath, "sqlitebackup.db");
                    //创建sqlite文件
                    SqliteHelper.NewSqliteDatabase(sqlitePath);
                    string fileBackupPath = filePath + "/filebackup";
                    if (!Directory.Exists(fileBackupPath))
                    {
                        Directory.CreateDirectory(fileBackupPath);
                    }
                    //往sqlite里面添加和插入表数据
                    ec_project_bakupIBLL.CreateAndAddBySqlit(ProjectId, list_tblName, sqlitePath, fileBackupPath, ProjectIndex);           
                    //提交
                    SqliteHelper.SaveChange();

                    //将集合生成为压缩文件
                    ZipOutputStream stream = new ZipOutputStream(SystemIO.File.Create(ZipFilesPath));
                    stream.SetLevel(0); // 压缩级别 0-9
                    byte[] buffer = new byte[4096]; //缓冲区大小
                    string[] filenames = Directory.GetFiles(filePath, "*.*", SearchOption.AllDirectories);
                    foreach (string file in filenames)
                    {
                        ZipEntry entry = new ZipEntry(file.Replace(filePath, ""));
                        stream.PutNextEntry(entry);

                        using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                            int sourceBytes;
                            do
                            {
                                sourceBytes = fs.Read(buffer, 0, buffer.Length);
                                stream.Write(buffer, 0, sourceBytes);
                            } while (sourceBytes > 0);
                        }
                    }
                    fileSize = stream.Length;

                    stream.Finish();
                    stream.Close();
                    //Directory.Delete(filePath.Replace('/', '\\'), true);
                }
                catch (Exception ex)
                {
                    SqliteHelper.Close();
                    Logger.Error($"项目备份异常：{ex.Message}");
                }
            }).ContinueWith(t => {
                //往数据库备份表中和附件表中插入数据
                ec_project_bakupIBLL.SaveEntity(ProjectId, ProjectName, ZipFilesPath, userInfo.userId, userInfo.realName, fileSize);
            });
            return Success("项目备份中...");
        }
        /// <summary>
        /// 项目还原
        /// </summary>
        /// <returns></returns>
        public ActionResult ProjectRestore(string ProjectIndex, string fileId)
        {
            try
            {
                //获取附件信息
                var annexesFile = new AnnexesFileBLL().GetByfolderIdEntity(fileId);
                if (annexesFile == null)
                {
                    return Fail("文件未上传完成，项目还原异常！！！");
                }
                var size = double.Parse(annexesFile.F_FileSize) / 1024 / 1024;
                if (size > 500)
                {
                    return Fail("ZIP文件大于限制值500M，项目还原异常！！！");
                }
                if (!string.IsNullOrWhiteSpace(annexesFile?.F_FilePath))
                {
                    string virtualPath = string.Format("{0}/{1}/{2}/{3}/{4}", Config.GetValue("AnnexesFile"), "BackupDecompress", LoginUserInfo.Get().userId, DateTime.Now.ToString("yyyyMMdd"), Guid.NewGuid().ToString("D"));
                    //如果解压目录不存在则创建
                    if (!Directory.Exists(virtualPath))
                    {
                        Directory.CreateDirectory(virtualPath);
                    }
                    Decompress(virtualPath, annexesFile.F_FilePath, ProjectIndex);
                }
            }
            catch (Exception ex)
            {
                return Fail("项目还原异常！");
            }
            return Success("项目还原成功！");
        }

        /// <summary>
        /// 解压zip格式的文件
        /// </summary>
        /// <param name="unZipDir">解压文件存放路径</param>
        /// <param name="zipFilePath">压缩文件路径</param>
        /// <param name="ProjectIndex">项目序号</param>
        /// <returns></returns>
        public void Decompress(string unZipDir, string zipFilePath, string ProjectIndex)
        {
            byte[] data = new byte[2048];
            int size = 2048;
            //一个ZIP文件中的条目，可以理解为压缩包里面的一个文件夹/文件
            ZipEntry theEntry = null;
            //解压缩输出流，从压缩包中一个接一个的读出文档。
            using (ZipInputStream inputStream = new ZipInputStream(SystemIO.File.OpenRead(zipFilePath)))
            {
                while ((theEntry = inputStream.GetNextEntry()) != null)
                {
                    if (theEntry.IsDirectory)
                    {// 该结点是目录    
                        if (!Directory.Exists(unZipDir + "/" + theEntry.Name))
                        {
                            Directory.CreateDirectory(unZipDir + "/" + theEntry.Name);
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(theEntry.Name))
                        {
                            string fileName = unZipDir + theEntry.Name;
                            fileName = fileName.Replace('/', '\\');
                            if (!Directory.Exists(Path.GetDirectoryName(fileName)))//判断是否存在
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(fileName));//创建新路径
                            }
                            using (FileStream streamWriter = SystemIO.File.Create(fileName))
                            {
                                while (true)
                                {
                                    size = inputStream.Read(data, 0, data.Length);
                                    if (size <= 0) break;
                                    streamWriter.Write(data, 0, size);
                                }
                                streamWriter.Close();
                            }
                        }
                    }
                }
                inputStream.Close();
            }
            //从sqlite里面获取数据还原
            List<string> list_tblName = BackupTable.GetBackupTableList();
            string sqlitePath = unZipDir + "\\dbbackup\\sqlitebackup.db";//sqlite路径
            string fileBackupPath = unZipDir + "\\filebackup";//附件路径
            ec_project_bakupIBLL.RestoreBySqlite(list_tblName, sqlitePath, fileBackupPath, ProjectIndex);
        }

        /// <summary>
        ///  下载备份文件 
        /// </summary>
        public void BackupDown(string projectBakupID)
        {
            //根据项目ID获取备份数据
            var data = ec_project_bakupIBLL.GetEntity(projectBakupID);
            if (data != null)
            {
                var annexesFile = new AnnexesFileBLL().GetList(data.FolderId).First();
                if (!string.IsNullOrEmpty(annexesFile?.F_FilePath))
                {
                    FileInfo fileinfo = new SystemIO.FileInfo(annexesFile?.F_FilePath);
                    if (fileinfo.Exists)
                    {
                        string filename = data.BakupName + ".zip";
                        FileStream fs = new FileStream(annexesFile?.F_FilePath, SystemIO.FileMode.Open);
                        byte[] bytes = new byte[(int)fs.Length];
                        fs.Read(bytes, 0, bytes.Length);
                        fs.Close();
                        Response.Charset = "UTF-8";
                        Response.ContentEncoding = Encoding.GetEncoding("UTF-8");
                        Response.ContentType = "application/octet-stream";
                        Response.AddHeader("Content-Disposition", "attachment; filename=" + Server.UrlEncode(filename));
                        Response.BinaryWrite(bytes);
                        Response.Flush();
                        Response.End();
                    }
                }
            }
        }

        #endregion
    }
}
